require('dotenv').config()
require('./config/alias')  // 引入别名配置
const express = require('express')
const cors = require('cors')
const path = require('path')
const routes = require('@routes')
const errorHandler = require('@middlewares/error-handler')
const logger = require('@shared/utils/logger')
const morgan = require('morgan')
const swaggerUi = require('swagger-ui-express')
const YAML = require('yamljs')
const envConfig = require('@config/env')
const adminRoutes = require('@routes/admin')
const miniappRoutes = require('@routes/miniapp')
const uploadRoutes = require('./routes/upload') // 添加新的上传路由
const models = require('@models')
const sequelize = models.sequelize // 从模型中获取已初始化的 sequelize 实例
const helmet = require('helmet')
const compression = require('compression')

const app = express()

// 设置CORS配置
const corsOptions = {
  origin: function (origin, callback) {
    // 允许所有来源访问，当您的前后端在不同域时需要
    callback(null, true);
  },
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Total-Count'],
  exposedHeaders: ['Content-Type', 'X-Total-Count'],
  credentials: false, // 对于图片等静态资源，不需要发送凭证
  maxAge: 86400 // 预检请求缓存24小时
};

// 应用CORS中间件到所有路由
app.use(cors(corsOptions));

// 为uploads目录下的资源添加特殊的CORS头
app.use('/public/uploads', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.header('Access-Control-Allow-Credentials', 'false');
  res.header('Access-Control-Max-Age', '86400'); // 24小时
  
  // 对于图片类型，设置更长的缓存
  if (req.path.match(/\.(jpg|jpeg|png|gif|webp)$/i)) {
    res.header('Cache-Control', 'public, max-age=86400'); // 24小时
  }
  
  next();
});

// 中间件
app.use(morgan('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(helmet())
app.use(compression())

// 添加处理原始请求体的中间件，用于处理微信支付回调的XML数据
app.use((req, res, next) => {
  if (req.headers['content-type'] === 'text/xml' || req.headers['content-type'] === 'application/xml') {
    let data = '';
    req.setEncoding('utf8');
    req.on('data', chunk => {
      data += chunk;
    });
    req.on('end', () => {
      req.rawBody = data;
      next();
    });
  } else {
    next();
  }
});

// 静态文件服务
app.use('/uploads', express.static(path.join(__dirname, '../uploads')))
app.use('/public', express.static(path.join(__dirname, '../public')))
app.use(express.static(path.join(__dirname, '../public'))) // 允许直接访问public目录下的文件

// 添加错误处理中间件
app.use('/uploads/*', (err, req, res, next) => {
  console.error('静态文件访问错误:', err);
  res.status(404).json({
    code: 404,
    message: '文件不存在'
  });
});

// API文档
const swaggerDocument = YAML.load(path.join(__dirname, '../swagger.yaml'))
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))

// 路由
app.use('/api', routes)  // 基础路由
app.use('/api/admin', adminRoutes)  // 管理后台路由
app.use('/api/miniapp', miniappRoutes)  // 小程序路由
app.use('/api/upload', uploadRoutes)  // 添加新的上传路由

// 错误处理
app.use(errorHandler)

// 404处理
app.use((req, res) => {
  if (req.path.startsWith('/api/')) {
    return res.status(404).json({
      code: 404,
      message: '接口不存在'
    })
  }
  res.status(404).json({
    code: 404,
    message: '接口不存在'
  })
})

const PORT = process.env.PORT || 3001
let server

// 数据库同步配置
// 环境变量控制是否执行同步
const shouldSync = process.env.NODE_ENV === 'development' 
  ? process.env.SYNC_DB !== 'false'  // 开发环境默认执行
  : process.env.SYNC_DB === 'true';  // 生产环境默认不执行

// 允许在开发环境中通过环境变量强制重建表
const forceSync = process.env.FORCE_SYNC === 'true';

// 数据库同步和初始化
const initDatabase = async () => {
  if (shouldSync) {
    try {
      const sequelize = models.sequelize;
      
      // 检查 sequelize 是否正确初始化
      if (!sequelize || typeof sequelize.sync !== 'function') {
        logger.error('数据库同步失败: Sequelize 实例未正确初始化');
        logger.error('sequelize 实例:', sequelize);
        return;
      }
      
      logger.info(`正在同步数据库结构... ${forceSync ? '(强制重建表)' : ''}`);
      await sequelize.sync({ 
        alter: !forceSync, // 当 force 为 true 时，不需要 alter
        force: forceSync
      });
      logger.info('数据库同步完成');
      
      // 如果设置了添加种子数据的环境变量
      if (process.env.SEED_DB === 'true' || forceSync) {
        logger.info('正在添加种子数据...');
        // 添加默认管理员
        await models.Admin.findOrCreate({
          where: { username: 'admin' },
          defaults: {
            password: '123456',
            name: '系统管理员',
            status: 1
          }
        });
        logger.info('种子数据添加完成');
      }
    } catch (err) {
      logger.error('数据库同步失败:', err);
    }
  } else {
    logger.info('数据库自动同步已禁用。若需同步数据库，请在.env文件中设置以下环境变量:');
    logger.info('SYNC_DB=true - 启用数据库同步');
    logger.info('FORCE_SYNC=true - 强制重建所有表 (谨慎使用，会删除现有数据)');
    logger.info('SEED_DB=true - 添加初始测试数据');
  }
};

const startServer = async () => {
  try {
    // 先初始化数据库
    await initDatabase();
    
    server = app.listen(PORT, () => {
      logger.info(`服务器运行在 http://localhost:${PORT}`)
    });

    // 保持服务器运行
    server.keepAliveTimeout = 65000; // 65 seconds
    server.headersTimeout = 66000; // 66 seconds

    // 处理未捕获的异常
    process.on('uncaughtException', (error) => {
      logger.error('未捕获的异常:', error)
      // 不要立即关闭，记录错误并继续运行
      logger.error('服务器继续运行...')
    })

    // 处理未处理的 Promise 拒绝
    process.on('unhandledRejection', (reason, promise) => {
      logger.error('未处理的 Promise 拒绝:', reason)
      // 不要立即关闭，记录错误并继续运行
      logger.error('服务器继续运行...')
    })

    // 处理进程终止信号
    process.on('SIGTERM', () => gracefulShutdown('SIGTERM'))
    process.on('SIGINT', () => gracefulShutdown('SIGINT'))

    return server;
  } catch (error) {
    logger.error('服务器启动失败:', error)
    throw error;
  }
}

// 优雅关闭服务器
const gracefulShutdown = (signal) => {
  logger.info(`收到信号 ${signal}，正在关闭服务器...`)
  if (server) {
    server.close(() => {
      logger.info('服务器已关闭')
      process.exit(0)
    })

    // 如果 10 秒内没有正常关闭，强制退出
    setTimeout(() => {
      logger.error('强制关闭服务器')
      process.exit(1)
    }, 10000)
  }
}

// 启动服务器并保持运行
const run = async () => {
  try {
    await startServer();
    logger.info('服务器启动成功');
    
    // 保持进程运行
    setInterval(() => {
      logger.info('服务器运行正常，时间:', new Date().toISOString());
    }, 30000);
    
  } catch (err) {
    logger.error('服务器启动失败，5秒后重试:', err);
    setTimeout(run, 5000);
  }
};

run().catch(err => {
  logger.error('启动过程出错:', err);
  process.exit(1);
});

module.exports = app